#include "main.h"
#include "pwm.h"
#include <stdio.h>
#include "systick.h"

uint32_t FK_COUNT01 = 0;
uint16_t FK_COUNT02 = 0;

uint32_t COUNT01 = 0;
uint16_t COUNT02 = 0;

uint16_t readvalue1 = 0, readvalue2 = 0;
__IO uint16_t ccnumber = 0;
__IO uint32_t count = 0;
__IO uint16_t fre = 0;
__IO uint16_t new_fre = 0;

uint32_t GetTimerCount(void)
{
    return FK_COUNT01;
}

uint32_t GetFreq(void)
{
    return fre;
}

void ClearFreq(void)
{
    fre = 0;
}
#if 0
/**
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
  */
void timer_config(void)
{
    /* ----------------------------------------------------------------------------
    TIMER1 Configuration:
    TIMER1CLK = SystemCoreClock/12000 = 10KHz, the period is 1s(10000/10000 = 1s).
    ---------------------------------------------------------------------------- */
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_TIMER1);

    timer_deinit(TIMER1);
    /* initialize TIMER init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* TIMER1 configuration */
    timer_initpara.prescaler         = 799;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 9999;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_init(TIMER1, &timer_initpara);

    /* enable the TIMER interrupt */
    timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
    timer_interrupt_enable(TIMER1, TIMER_INT_UP);

    timer_enable(TIMER1);

    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(TIMER1_IRQn, 1, 1);
}

/*!
    \brief      this function handles TIMER1 interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TIMER1_IRQHandler(void)
{
    if(SET == timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_UP)) {
        /* clear update interrupt bit */
        timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
    	// printf("timer1 intrrupt COUNT01 = %d\r\n", COUNT01);
		FK_COUNT01 = COUNT01;
		COUNT01 = 0;
    }
}

void tach_config(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);
	gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1);

    /* connect key EXTI line to key GPIO pin */
    gpio_exti_source_select(GPIO_EVENT_PORT_GPIOA, GPIO_EVENT_PIN_1);

    /* configure key EXTI line */
    exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_RISING);    // 上升沿
	//exti_init(EXTI_1, EXTI_INTERRUPT, EXTI_TRIG_BOTH);

	nvic_irq_enable(EXTI1_IRQn, 0, 0);
}

uint8_t COUNT0FLAG = 0;
void EXTI1_IRQHandler(void)
{
	uint8_t flag = 0;
	if(RESET != exti_interrupt_flag_get(EXTI_1)) {
        exti_interrupt_flag_clear(EXTI_1);
#if 0
		flag = gpio_input_bit_get(GD32_TACH2_PORT, GD32_TACH2_PIN);
		if(flag != COUNT0FLAG){
			COUNT01++;
		}
		COUNT0FLAG = flag;
#endif
        COUNT01++;
    }
}
#endif
/**
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
  */
void timer_configuration(void)
{
    /* TIMER1 configuration: input capture mode -------------------
    the external signal is connected to TIMER1 CH0 pin (PA6)
    the rising edge is used as active edge
    the TIMER1 CH0CV is used to compute the frequency value
    ------------------------------------------------------------ */
    timer_ic_parameter_struct timer_icinitpara;
    timer_parameter_struct timer_initpara;

    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);
    rcu_periph_clock_enable(RCU_TIMER1);

    /*configure PA1 (TIMER1 CH0) as alternate function*/
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1);

    timer_deinit(TIMER1);
    /* initialize TIMER init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* TIMER1 configuration */
    timer_initpara.prescaler = 7;
    timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection = TIMER_COUNTER_UP;
    timer_initpara.period = 65535;
    timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER1, &timer_initpara);

    /* TIMER1  configuration */
    /* initialize TIMER channel input parameter struct */
    timer_channel_input_struct_para_init(&timer_icinitpara);
    /* TIMER1 CH1 input capture configuration */
    timer_icinitpara.icpolarity = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter = 0x0;
    timer_input_capture_config(TIMER1, TIMER_CH_1, &timer_icinitpara);

    /* auto-reload preload enable */
    timer_auto_reload_shadow_enable(TIMER1);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH1);
    /* channel 0 interrupt enable */
    // timer_interrupt_enable(TIMER1, TIMER_INT_CH1);

    // nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(TIMER1_IRQn, 1, 3);

    /* TIMER1 counter enable */
    // timer_enable(TIMER1);
}

/*!
    \brief      this function handles TIMER1 interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void TIMER1_IRQHandler(void)
{
    if (SET == timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_CH1))
    {
        /* clear channel 0 interrupt bit */
        timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_CH1);

        if (0 == ccnumber)
        {
            /* read channel 0 capture value */
            readvalue1 = timer_channel_capture_value_register_read(TIMER1, TIMER_CH_1);
            ccnumber = 1;
        }
        else if (1 == ccnumber)
        {
            /* read channel 0 capture value */
            readvalue2 = timer_channel_capture_value_register_read(TIMER1, TIMER_CH_1);

            if (readvalue2 > readvalue1)
            {
                count = (readvalue2 - readvalue1);
            }
            else
            {
                count = ((0xFFFFU - readvalue1) + readvalue2);
            }
            ccnumber = 0;
            new_fre = (1000000 / count);
            // new_fre = (rcu_clock_freq_get(CK_APB1) / count)/10;
            //  printf("calc freq: %d Hz\r\n", new_fre);
            if ((new_fre > 25) && (new_fre < 330)) // 适配2种风扇的信号反馈
            {
                fre = new_fre;
                // printf("fre = %d\r\n", fre);
            }
        }
    }
}

/*
    分为4个等级
        level1: 50%（duty）
        level2: 70%（duty）
        level3: 80%（duty）
        level4: 99%（duty）
*/
void fan_pwm_set(uint8_t level)
{
    uint32_t pulse = 0;
    uint8_t duty[4] = {50, 70, 80, 97};

    pulse = PWM_DUTYCALC(duty[level - 1]);
    printf("setting PWM pulse: %d\r\n", duty[level - 1]);

    timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER4, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER4, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER4, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER3, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER3, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER3, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER3, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER2, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER2, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);

    timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, pulse);
    timer_channel_output_mode_config(TIMER11, TIMER_CH_1, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER11, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
}

void powerup_fan_pwm_set(uint8_t level)
{
    uint32_t pulse = 0;
    uint8_t duty[5] = {20, 40, 60, 80, 97};

    pulse = PWM_DUTYCALC(duty[level - 1]);
    printf("setting PWM pulse: %d\r\n", duty[level - 1]);

    timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER4, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER4, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER4, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER0, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER0, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER3, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER3, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER3, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER3, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER3, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_2, pulse);
    timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER2, TIMER_CH_2, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER2, TIMER_CH_3, pulse);
    timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER2, TIMER_CH_3, TIMER_OC_SHADOW_DISABLE);
    delay_1ms(100);
    timer_channel_output_pulse_value_config(TIMER11, TIMER_CH_1, pulse);
    timer_channel_output_mode_config(TIMER11, TIMER_CH_1, TIMER_OC_MODE_PWM0);
    timer_channel_output_shadow_config(TIMER11, TIMER_CH_1, TIMER_OC_SHADOW_DISABLE);
}